home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / ToolManager / Source / Library / image.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  18KB  |  685 lines

  1. /*
  2.  * image.c  V3.1
  3.  *
  4.  * ToolManager Objects Image class
  5.  *
  6.  * Copyright (C) 1990-98 Stefan Becker
  7.  *
  8.  * This source code is for educational purposes only. You may study it
  9.  * and copy ideas or algorithms from it for your own projects. It is
  10.  * not allowed to use any of the source codes (in full or in parts)
  11.  * in other programs. Especially it is not allowed to create variants
  12.  * of ToolManager or ToolManager-like programs from this source code.
  13.  *
  14.  */
  15.  
  16. #include "toolmanager.h"
  17.  
  18. /* Local data */
  19. #define PROPCHUNKS 1
  20. static const ULONG PropChunkTable[2 * PROPCHUNKS] = {
  21.  ID_TMIM, ID_FILE
  22. };
  23. static ULONG           IconLockCount      = 0;
  24. static struct Library *IconBase           = NULL;
  25. static ULONG           DataTypesLockCount = 0;
  26. static struct Library *DataTypesBase      = NULL;
  27. static ULONG           RemapEnabled       = TRUE;
  28. static ULONG           RemapPrecision     = PRECISION_IMAGE;
  29.  
  30. /* Local data structures */
  31. struct TMCacheData {
  32.  struct MinNode  tmcd_Node;
  33.  Object         *tmcd_DTObject;
  34.  struct Screen  *tmcd_Screen;
  35.  ULONG           tmcd_References;
  36. };
  37.  
  38. struct TMBitMapData {
  39.  struct TMImageData  tmbmd_Data;
  40.  struct TMCacheData *tmbmd_CacheEntry;
  41. };
  42.  
  43. #define IMAGE_TYPE_BITMAP 0 /* For TMImageData.tmid_Type */
  44. #define IMAGE_TYPE_ICON   1
  45.  
  46. /* Image class instance data */
  47. struct ImageClassData {
  48.  ULONG           icd_Flags;
  49.  char           *icd_File;
  50.  struct MinList  icd_Cache;
  51. };
  52. #define TYPED_INST_DATA(cl, o) ((struct ImageClassData *) INST_DATA((cl), (o)))
  53.  
  54. /* Flags for strings allocated in IFF parsing */
  55. #define IFFF_FILE       0x80000000  /* icd_File */
  56.  
  57. /* Internal state flags */
  58. #define IMAGEF_DELETING 0x00000001  /* Object is in delete state */
  59.  
  60. #ifdef _DCC
  61. /* VarArgs stub for DoDTMethodA */
  62. ULONG DoDTMethod(Object *obj, struct Window *w, struct Requester *req,
  63.                  ULONG MethodID, ...)
  64. {
  65.  return(DoDTMethodA(obj, w, req, (Msg) &MethodID));
  66. }
  67.  
  68. /* VarArgs stub for GetDTAttrsA */
  69. ULONG GetDTAttrs(Object *obj, Tag tag1, ...)
  70. {
  71.  return(GetDTAttrsA(obj, (struct Tagitem *) &tag1));
  72. }
  73.  
  74. /* VarArgs stub for NewDTObjectA */
  75. static Object *NewDTObject(APTR name, Tag tag1, ...)
  76. {
  77.  return(NewDTObjectA(name, (struct TagItem *) &tag1));
  78. }
  79.  
  80. /* VarArgs stub for SetDTAttrsA */
  81. ULONG SetDTAttrs(Object *obj, struct Window *w, struct Requester *req,
  82.                  Tag tag1, ...)
  83. {
  84.  return(SetDTAttrsA(obj, w, req, (struct Tagitem *) &tag1));
  85. }
  86. #endif
  87.  
  88. /* Open datatypes.library */
  89. static BOOL LockDataTypesLibrary(void)
  90. {
  91.  BOOL rc;
  92.  
  93.  /* Library already opened or can we open it? */
  94.  if (rc = (DataTypesBase != NULL) ||
  95.           (DataTypesBase = OpenLibrary("datatypes.library", 39)))
  96.  
  97.   /* Increment lock counter */
  98.   DataTypesLockCount++;
  99.  
  100.  return(rc);
  101. }
  102.  
  103. /* Close datatypes.library */
  104. static void ReleaseDataTypesLibrary(void)
  105. {
  106.  /* Decrement lock counter */
  107.  if (--DataTypesLockCount == 0) {
  108.  
  109.   /* Lock count is zero, close library */
  110.   CloseLibrary(DataTypesBase);
  111.  
  112.   /* Reset library base pointer */
  113.   DataTypesBase = NULL;
  114.  }
  115. }
  116.  
  117. /* Open a picture.datatype object */
  118. static Object *NewImageDTObject(const char *name, struct Screen *s)
  119. {
  120.  return(NewDTObject(name, DTA_SourceType, DTST_FILE,
  121.                           DTA_GroupID,    GID_PICTURE,
  122.                           PDTA_DestMode,  MODE_V43,
  123.                           PDTA_Remap,     RemapEnabled,
  124.                           OBP_Precision,  RemapPrecision,
  125.                           PDTA_Screen,    s,
  126.                           TAG_DONE));
  127. }
  128.  
  129. /* Get an entry from the cache. If it doesn't exist create a new one and */
  130. /* Try <file> and <file>.info as file name for the DataTypes object      */
  131. #undef  DEBUGFUNCTION
  132. #define DEBUGFUNCTION GetCacheEntry
  133. static struct TMCacheEntry *GetCacheEntry(const char *name, struct Screen *s,
  134.                                           struct MinList *l)
  135. {
  136.  struct TMCacheData *rc = (struct TMCacheData *) GetHead(l);;
  137.  
  138.  IMAGECLASS_LOG(LOG3(Arguments, "Name %s (0x%08lx) Screen 0x%08lx", name,
  139.                      name, s))
  140.  
  141.  /* Scan cache list */
  142.  while (rc) {
  143.  
  144.   /* Is the screen of the cache entry the same as the specified one? */
  145.   if (rc->tmcd_Screen == s) {
  146.  
  147.    /* Yes, increment reference count */
  148.    rc->tmcd_References++;
  149.  
  150.    /* Leave loop */
  151.    break;
  152.   }
  153.  
  154.   /* Next entry */
  155.   rc = (struct TMCacheData *) GetSucc((struct MinNode *) rc);
  156.  }
  157.  
  158.  /* Object not found in cache and can we lock the datatypes.library? */
  159.  if ((rc == NULL) && LockDataTypesLibrary()) {
  160.   struct TMCacheData *tmcd;
  161.  
  162.   IMAGECLASS_LOG(LOG0(Creating new cache entry))
  163.  
  164.   /* Yes, allocate memory for new cache entry */
  165.   if (tmcd = GetMemory(sizeof(struct TMCacheData))) {
  166.  
  167.    IMAGECLASS_LOG(LOG1(New cache entry, "0x%08lx", tmcd))
  168.  
  169.    /* Open DataTypes object, Try with original file name first */
  170.    if ((tmcd->tmcd_DTObject = NewImageDTObject(name, s)) == NULL) {
  171.     ULONG  len = strlen(name);
  172.     char  *buf;
  173.  
  174.     IMAGECLASS_LOG(LOG0(Object not loaded trying to load icon))
  175.  
  176.     /* Allocate memory for string */
  177.     if (buf = GetVector(len + sizeof(".info"))) {
  178.  
  179.      /* Copy string */
  180.      CopyMem(name, buf, len);
  181.  
  182.      /* Append ".info" */
  183.      CopyMem(".info", buf + len, sizeof(".info"));
  184.  
  185.      IMAGECLASS_LOG(LOG2(New name, "%s (0x%08lx)", buf, buf))
  186.  
  187.      /* Try again with new name */
  188.      tmcd->tmcd_DTObject = NewImageDTObject(buf, s);
  189.  
  190.      /* Free buffer */
  191.      FreeVector(buf);
  192.     }
  193.    }
  194.  
  195.    IMAGECLASS_LOG(LOG1(DTObject, "0x%08lx", tmcd->tmcd_DTObject))
  196.  
  197.    /* Datatypes object created? */
  198.    if (tmcd->tmcd_DTObject) {
  199.  
  200.     /* Yes, set object attributes */
  201.     SetDTAttrs(tmcd->tmcd_DTObject, NULL, NULL, PDTA_UseFriendBitMap, TRUE,
  202.                                                 TAG_DONE);
  203.  
  204.     /* Draw picture into destination bitmap */
  205.     if (DoDTMethod(tmcd->tmcd_DTObject, NULL, NULL,
  206.                    DTM_PROCLAYOUT, NULL, TRUE)) {
  207.  
  208.      /* Image remapped, initialize rest of cache entry */
  209.      tmcd->tmcd_Screen     = s;
  210.      tmcd->tmcd_References = 1;
  211.  
  212.      /* Add entry to cache */
  213.      AddTail((struct List *) l, (struct Node *) tmcd);
  214.  
  215.      /* Set return value */
  216.      rc = tmcd;
  217.     }
  218.    }
  219.  
  220.    /* Error? Free cache entry */
  221.    if (rc == NULL) FreeMemory(tmcd, sizeof(struct TMCacheData));
  222.   }
  223.  
  224.   /* Error? Release datatypes.library again */
  225.   if (rc == NULL) ReleaseDataTypesLibrary();
  226.  }
  227.  
  228.  IMAGECLASS_LOG(LOG1(Result, "0x%08lx", rc))
  229.  
  230.  /* Return pointer to cache entry */
  231.  return(rc);
  232. }
  233.  
  234. /* Remove one entry from cache list */
  235. #undef  DEBUGFUNCTION
  236. #define DEBUGFUNCTION RemoveCacheEntry
  237. static void RemoveCacheEntry(struct TMCacheData *tmcd)
  238. {
  239.  IMAGECLASS_LOG(LOG1(Removing, "0x%08lx", tmcd))
  240.  
  241.  /* Remove entry from list */
  242.  Remove((struct Node *) tmcd);
  243.  
  244.  /* Free DataTypes object */
  245.  DisposeDTObject(tmcd->tmcd_DTObject);
  246.  
  247.  /* Release datatypes.library */
  248.  ReleaseDataTypesLibrary();
  249.  
  250.  /* Free memory for cache entry */
  251.  FreeMemory(tmcd, sizeof(struct TMCacheData));
  252. }
  253.  
  254. /* Open icon.library */
  255. static BOOL LockIconLibrary(void)
  256. {
  257.  BOOL rc;
  258.  
  259.  /* Library already opened or can we open it? */
  260.  if (rc = (IconBase != NULL) ||
  261.           (IconBase = OpenLibrary("icon.library", 39)))
  262.  
  263.   /* Increment lock counter */
  264.   IconLockCount++;
  265.  
  266.  return(rc);
  267. }
  268.  
  269. /* Close icon.library */
  270. static void ReleaseIconLibrary(void)
  271. {
  272.  /* Decrement lock counter */
  273.  if (--IconLockCount == 0) {
  274.  
  275.   /* Lock count is zero, close library */
  276.   CloseLibrary(IconBase);
  277.  
  278.   /* Reset library base pointer */
  279.   IconBase = NULL;
  280.  }
  281. }
  282.  
  283. /* Image class method: OM_NEW */
  284. #undef  DEBUGFUNCTION
  285. #define DEBUGFUNCTION ImageClassNew
  286. static ULONG ImageClassNew(Class *cl, Object *obj, struct opSet *ops)
  287. {
  288.  IMAGECLASS_LOG((LOG1(Tags, "0x%08lx", ops->ops_AttrList),
  289.                  PrintTagList(ops->ops_AttrList)))
  290.  
  291.  /* Call SuperClass */
  292.  if (obj = (Object *) DoSuperMethodA(cl, obj, (Msg) ops)) {
  293.   struct ImageClassData *icd = TYPED_INST_DATA(cl, obj);
  294.  
  295.   /* Initialize instance data */
  296.   icd->icd_Flags = 0;
  297.   icd->icd_File  = NULL;
  298.  
  299.   /* Initialize bitmap cache list */
  300.   NewList((struct List *) &icd->icd_Cache);
  301.  }
  302.  
  303.  return((ULONG) obj);
  304. }
  305.  
  306. /* Image class method: OM_DISPOSE */
  307. #undef  DEBUGFUNCTION
  308. #define DEBUGFUNCTION ImageClassDispose
  309. static ULONG ImageClassDispose(Class *cl, Object *obj, Msg msg)
  310. {
  311.  struct ImageClassData *icd = TYPED_INST_DATA(cl, obj);
  312.  
  313.  IMAGECLASS_LOG(LOG0(Disposing))
  314.  
  315.  /* Purge cache to clear unreferenced objects first */
  316.  DoMethod(obj, TMM_PurgeCache);
  317.  
  318.  /* We are in delete state now */
  319.  icd->icd_Flags |= IMAGEF_DELETING;
  320.  
  321.  /* Free IFF data */
  322.  if (icd->icd_Flags & IFFF_FILE) FreeVector(icd->icd_File);
  323.  
  324.  /* Call SuperClass */
  325.  return(DoSuperMethodA(cl, obj, msg));
  326. }
  327.  
  328. /* Image class method: TMM_Detach */
  329. #undef  DEBUGFUNCTION
  330. #define DEBUGFUNCTION ImageClassDetach
  331. static ULONG ImageClassDetach(Class *cl, Object *obj, struct TMP_Detach *tmpd)
  332. {
  333.  IMAGECLASS_LOG(LOG2(Arguments, "Data 0x%08lx Member 0x%08lx",
  334.                      tmpd->tmpd_MemberData,
  335.                      tmpd->tmpd_MemberData->tmmd_Member))
  336.  
  337.  /* Icon or BitMap? */
  338.  if (((struct TMImageData *) tmpd->tmpd_MemberData)->tmid_Type
  339.       == IMAGE_TYPE_BITMAP) {
  340.   struct TMCacheData *tmcd = ((struct TMBitMapData *)
  341.                               tmpd->tmpd_MemberData)->tmbmd_CacheEntry;
  342.  
  343.   /* Cache entry valid? */
  344.   if (tmcd) {
  345.  
  346.    IMAGECLASS_LOG(LOG1(Decrement reference, "0%08lx", tmcd))
  347.  
  348.    /* Decrement reference count for cache entry */
  349.    tmcd->tmcd_References--;
  350.   }
  351.  
  352.  } else {
  353.  
  354.   IMAGECLASS_LOG(LOG0(Releasing Icon))
  355.  
  356.   /* Free Icon */
  357.   FreeDiskObject(((struct TMImageData *) tmpd->tmpd_MemberData)
  358.                   ->tmid_ImageData);
  359.   ReleaseIconLibrary();
  360.  }
  361.  
  362.  /* Call SuperClass */
  363.  return(DoSuperMethodA(cl, obj, (Msg) tmpd));
  364. }
  365.  
  366. /* Image class method: TMM_ParseIFF */
  367. #undef  DEBUGFUNCTION
  368. #define DEBUGFUNCTION ImageClassParseIFF
  369. static ULONG ImageClassParseIFF(Class *cl, Object *obj,
  370.                                 struct TMP_ParseIFF *tmppi)
  371. {
  372.  BOOL rc = FALSE;
  373.  
  374.  IMAGECLASS_LOG(LOG1(Handle, "0x%08lx", tmppi->tmppi_IFFHandle))
  375.  
  376.  /* Initialize IFF parser and forward method to SuperClass */
  377.  if ((PropChunks(tmppi->tmppi_IFFHandle, PropChunkTable, PROPCHUNKS) == 0) &&
  378.      DoSuperMethodA(cl, obj, (Msg) tmppi)) {
  379.   char *file;
  380.  
  381.   IMAGECLASS_LOG(LOG0(FORM TMIM chunk parsed OK))
  382.  
  383.   /* Check for mandatory FILE property */
  384.   if (file = DuplicateProperty(tmppi->tmppi_IFFHandle, ID_TMIM, ID_FILE)) {
  385.    struct ImageClassData *icd = TYPED_INST_DATA(cl, obj);
  386.  
  387.    IMAGECLASS_LOG(LOG2(File, "%s (0x%08lx)", file, file))
  388.  
  389.    /* Set instance data */
  390.    icd->icd_Flags = IFFF_FILE;
  391.    icd->icd_File  = file;
  392.  
  393.    /* Configuration data parsed */
  394.    rc = TRUE;
  395.   }
  396.  }
  397.  
  398.  IMAGECLASS_LOG(LOG1(Result, "%ld", rc))
  399.  
  400.  return(rc);
  401. }
  402.  
  403. /* Image class method: TMM_ParseTags */
  404. #undef  DEBUGFUNCTION
  405. #define DEBUGFUNCTION ImageClassParseTags
  406. static ULONG ImageClassParseTags(Class *cl, Object *obj,
  407.                                  struct TMP_ParseTags *tmppt)
  408. {
  409.  struct ImageClassData *icd    = TYPED_INST_DATA(cl, obj);
  410.  struct TagItem        *tstate = tmppt->tmppt_Tags;
  411.  struct TagItem        *ti;
  412.  BOOL                   rc     = FALSE;
  413.  
  414.  IMAGECLASS_LOG((LOG1(Tags, "0x%08lx", tmppt->tmppt_Tags),
  415.                 PrintTagList(tmppt->tmppt_Tags)))
  416.  
  417.  /* Scan tag list */
  418.  while (ti = NextTagItem(&tstate))
  419.  
  420.   /* File tag and valid data? */
  421.   if ((ti->ti_Tag == TMOP_File) && ti->ti_Data) {
  422.  
  423.    /* Set new file */
  424.    icd->icd_File = (char *) ti->ti_Data;
  425.  
  426.    /* All OK */
  427.    rc = TRUE;
  428.   }
  429.  
  430.  /* All OK? */
  431.  if (rc) {
  432.  
  433.   /* Yes, forward method to SuperClass */
  434.   rc = DoSuperMethodA(cl, obj, (Msg) tmppt);
  435.  
  436.   /* Purge cache after all attached objects have been notified */
  437.   DoMethod(obj, TMM_PurgeCache);
  438.  }
  439.  
  440.  IMAGECLASS_LOG(LOG1(Result, "%ld", rc))
  441.  
  442.  return(rc);
  443. }
  444.  
  445. /* Image class method: TMM_GetImage */
  446. #undef  DEBUGFUNCTION
  447. #define DEBUGFUNCTION ImageClassGetImage
  448. static ULONG ImageClassGetImage(Class *cl, Object *obj,
  449.                                 struct TMP_GetImage *tmpgi)
  450. {
  451.  ULONG rc = 0;
  452.  
  453.  IMAGECLASS_LOG(LOG2(Arguments, "Object 0x%08lx Screen 0x%08lx",
  454.                      tmpgi->tmpgi_Object, tmpgi->tmpgi_Screen))
  455.  
  456.  /* Icon or BitMap? */
  457.  if (tmpgi->tmpgi_Screen == NULL) {
  458.   struct TMImageData *tmid;
  459.  
  460.   /* Load icon. Call SuperClass to allocate TMImageData */
  461.   if (tmid = (struct TMImageData *) DoSuperMethod(cl, obj, TMM_Attach,
  462.                                      tmpgi->tmpgi_Object,
  463.                                      sizeof(struct TMImageData))) {
  464.  
  465.    IMAGECLASS_LOG(LOG1(TMImageData, "0x%08lx", tmid))
  466.  
  467.    /* Open icon.library */
  468.    if (LockIconLibrary()) {
  469.  
  470.     IMAGECLASS_LOG(LOG0(Icon Library opened))
  471.  
  472.     /* Read icon */
  473.     if (tmid->tmid_ImageData =
  474.          GetDiskObject(TYPED_INST_DATA(cl, obj)->icd_File)) {
  475.  
  476.      IMAGECLASS_LOG(LOG1(DiskObject, "0x%08lx", tmid->tmid_ImageData))
  477.  
  478.      /* Initialize data structure */
  479.      tmid->tmid_Type   = IMAGE_TYPE_ICON;
  480.      tmid->tmid_Width  = ((struct DiskObject *) tmid->tmid_ImageData)
  481.                           ->do_Gadget.Width;
  482.      tmid->tmid_Height = ((struct DiskObject *) tmid->tmid_ImageData)
  483.                           ->do_Gadget.Height;
  484.  
  485.      /* All OK */
  486.      rc = (ULONG) tmid;
  487.  
  488.     } else
  489.      ReleaseIconLibrary();
  490.    }
  491.  
  492.    /* If we couldn't get the icon, detach the object again */
  493.    if (rc == 0) DoSuperMethod(cl, obj, TMM_Detach, tmid);
  494.   }
  495.  
  496.  } else {
  497.   struct TMBitMapData *tmbmd;
  498.  
  499.   /* Load BitMap. Call SuperClass to allocate TMImageData */
  500.   if (tmbmd = (struct TMBitMapData *) DoSuperMethod(cl, obj, TMM_Attach,
  501.                                        tmpgi->tmpgi_Object,
  502.                                        sizeof(struct TMBitMapData))) {
  503.    struct ImageClassData *icd = TYPED_INST_DATA(cl, obj);
  504.  
  505.    IMAGECLASS_LOG(LOG1(TMBitMapData, "0x%08lx", tmbmd))
  506.  
  507.    /* Initialize data structure type */
  508.    tmbmd->tmbmd_Data.tmid_Type = IMAGE_TYPE_BITMAP;
  509.  
  510.    /* Create datatypes object */
  511.    if (tmbmd->tmbmd_CacheEntry = GetCacheEntry(icd->icd_File,
  512.                                                tmpgi->tmpgi_Screen,
  513.                                                &icd->icd_Cache)) {
  514.     struct BitMapHeader *bmh;
  515.  
  516.     /* Get bitmap information */
  517.     if (GetDTAttrs(tmbmd->tmbmd_CacheEntry->tmcd_DTObject,
  518.                          PDTA_DestBitMap,   &tmbmd->tmbmd_Data.tmid_ImageData,
  519.                          PDTA_BitMapHeader, &bmh,
  520.                          TAG_DONE)) {
  521.  
  522.      IMAGECLASS_LOG(LOG3(BitMap, "0x%08lx (%ld x %ld)",
  523.                          tmbmd->tmbmd_Data.tmid_ImageData,
  524.                          bmh->bmh_Width, bmh->bmh_Height))
  525.  
  526.      /* Initialize data structure */
  527.      tmbmd->tmbmd_Data.tmid_Width  = bmh->bmh_Width;
  528.      tmbmd->tmbmd_Data.tmid_Height = bmh->bmh_Height;
  529.  
  530.      /* All OK */
  531.      rc = (ULONG) tmbmd;
  532.     }
  533.    }
  534.  
  535.    /* If we couldn't get the object, detach the object again */
  536.    if (rc == 0) DoMethod(obj, TMM_Detach, tmbmd);
  537.   }
  538.  }
  539.  
  540.  IMAGECLASS_LOG(LOG1(Result, "0x%08lx", rc))
  541.  
  542.  /* Return pointer to image data */
  543.  return(rc);
  544. }
  545.  
  546. /* Image class method: TMM_PurgeCache */
  547. #undef  DEBUGFUNCTION
  548. #define DEBUGFUNCTION ImageClassPurgeCache
  549. static ULONG ImageClassPurgeCache(Class *cl, Object *obj)
  550. {
  551.  struct TMCacheData *tmcd = (struct TMCacheData *)
  552.                              GetHead(&TYPED_INST_DATA(cl, obj)->icd_Cache);
  553.  
  554.  IMAGECLASS_LOG(LOG0(Clearing cache))
  555.  
  556.  /* Scan cache list */
  557.  while (tmcd) {
  558.   struct TMCacheData *next = (struct TMCacheData *)
  559.                               GetSucc((struct MinNode *) tmcd);
  560.  
  561.   /* Cache entry unreferenced? Remove entry from cache */
  562.   if (tmcd->tmcd_References == 0) RemoveCacheEntry(tmcd);
  563.  
  564.   /* Next entry */
  565.   tmcd = next;
  566.  }
  567.  
  568.  /* Return 1 to indicate that the method is implemented */
  569.  return(1);
  570. }
  571.  
  572. /* Image class method: TMM_ScreenClose */
  573. #undef  DEBUGFUNCTION
  574. #define DEBUGFUNCTION ImageClassScreenClose
  575. static ULONG ImageClassScreenClose(Class *cl, Object *obj,
  576.                                    struct TMP_ScreenClose *tmpsc)
  577. {
  578.  struct TMCacheData *tmcd = (struct TMCacheData *)
  579.                              GetHead(&TYPED_INST_DATA(cl, obj)->icd_Cache);
  580.  
  581.  IMAGECLASS_LOG(LOG1(Arguments, "Screen 0x%08lx", tmpsc->tmpsc_Screen))
  582.  
  583.  /* Scan cache list */
  584.  while (tmcd) {
  585.   struct TMCacheData *next = (struct TMCacheData *)
  586.                               GetSucc((struct MinNode *) tmcd);
  587.  
  588.   /* Cache entry uses the screen? Remove entry from cache */
  589.   if (tmcd->tmcd_Screen == tmpsc->tmpsc_Screen) RemoveCacheEntry(tmcd);
  590.  
  591.   /* Next entry */
  592.   tmcd = next;
  593.  }
  594.  
  595.  /* Return 1 to indicate that the method is implemented */
  596.  return(1);
  597. }
  598.  
  599. /* Image class dispatcher */
  600. #undef  DEBUGFUNCTION
  601. #define DEBUGFUNCTION ImageClassDispatcher
  602. static __geta4 ULONG ImageClassDispatcher(__A0 Class *cl, __A2 Object *obj,
  603.                                           __A1 Msg msg)
  604. {
  605.  ULONG rc;
  606.  
  607.  IMAGECLASS_LOG(LOG3(Arguments, "Class 0x%08lx Object 0x%08lx Msg 0x%08lx",
  608.                      cl, obj, msg))
  609.  
  610.  switch(msg->MethodID) {
  611.   /* BOOPSI methods */
  612.   case OM_NEW:
  613.    rc = ImageClassNew(cl, obj, (struct opSet *) msg);
  614.    break;
  615.  
  616.   case OM_DISPOSE:
  617.    rc = ImageClassDispose(cl, obj, msg);
  618.    break;
  619.  
  620.   /* TM methods */
  621.   case TMM_Detach:
  622.    rc = ImageClassDetach(cl, obj, (struct TMP_Detach *) msg);
  623.    break;
  624.  
  625.   case TMM_ParseIFF:
  626.    rc = ImageClassParseIFF(cl, obj, (struct TMP_ParseIFF *) msg);
  627.    break;
  628.  
  629.   case TMM_ParseTags:
  630.    rc = ImageClassParseTags(cl, obj, (struct TMP_ParseTags *) msg);
  631.    break;
  632.  
  633.   case TMM_GetImage:
  634.    rc = ImageClassGetImage(cl, obj, (struct TMP_GetImage *) msg);
  635.    break;
  636.  
  637.   case TMM_PurgeCache:
  638.    rc = ImageClassPurgeCache(cl, obj);
  639.    break;
  640.  
  641.   case TMM_ScreenClose:
  642.    rc = ImageClassScreenClose(cl, obj, (struct TMP_ScreenClose *) msg);
  643.    break;
  644.  
  645.   /* Unknown method -> delegate to SuperClass */
  646.   default:
  647.    rc = DoSuperMethodA(cl, obj, msg);
  648.    break;
  649.  }
  650.  
  651.  return(rc);
  652. }
  653.  
  654. /* Create Image class */
  655. #undef  DEBUGFUNCTION
  656. #define DEBUGFUNCTION CreateImageClass
  657. Class *CreateImageClass(Class *superclass)
  658. {
  659.  Class *cl;
  660.  
  661.  IMAGECLASS_LOG(LOG1(SuperClass, "0x%08lx", superclass))
  662.  
  663.  /* Create class */
  664.  if (cl = MakeClass(NULL, NULL, superclass, sizeof(struct ImageClassData), 0))
  665.  
  666.   /* Set dispatcher */
  667.   cl->cl_Dispatcher.h_Entry = (ULONG (*)()) ImageClassDispatcher;
  668.  
  669.  IMAGECLASS_LOG(LOG1(Class, "0x%08lx", cl))
  670.  
  671.  /* Return pointer to class */
  672.  return(cl);
  673. }
  674.  
  675. /* Enable/Disable remapping */
  676. #undef  DEBUGFUNCTION
  677. #define DEBUGFUNCTION EnableRemap
  678. void EnableRemap(BOOL enable, ULONG precision)
  679. {
  680.  IMAGECLASS_LOG(LOG2(Data, "Enable %ld, Precision %ld", enable, precision))
  681.  
  682.  RemapEnabled   = enable;
  683.  RemapPrecision = precision;
  684. }
  685.